// 任务队列
import { define } from 'cydon'
import { Task } from '../type'
import { CTable } from './CTable'
import { getTile, put, setProc, toCoord, tryApply } from '../game'
import { updatables } from '../tino'
import { error } from '@cydon/ui/Message'
import { errors, names } from '../defs'
import { world } from '../store'
import { processData } from '../util'
import { CPagination } from './CPagination'
import { DataFilter } from './DataFilter'
import { updateTechs } from './TechTree'
import { getRecipes } from '../recipes'
import view from '../view'

type TaskBase = Omit<Task, 'time' | 'oldValue'>

const [gameMenu] = document.getElementsByTagName('game-menu')

/** 完成任务 */
function finish(task: Task) {
	const slot = task.slot
	if (task.value < 0) {
		world.techs.add(task.name.substring(2))
		updateTechs()
	} else {
		put(slot, task.value)
		const id = task.value & 0xff
		const [recipe] = getRecipes(id)
		if (recipe)
			setProc(slot, recipe.id, recipe.period)

		if (slot == view.selectedSlot)
			gameMenu.updateValue('selectedSlot')
	}
	world.tasks.splice(world.tasks.findIndex(select(task)), 1)
	const stats = world.stats
	switch (task.name.substring(0, 2)) {
		case '建造':
			stats.totalBuild++
			break
		case '升级':
			stats.totalUpgrade++
			break
		case '降级':
		case '拆除':
			stats.totalDestroy++
			break
	}
}

/**
 * @element q-table
 * 任务队列表格
 */
@define('q-table')
export class QTable extends CTable<Task> {
	static observedAttributes = super.observedAttributes

	/** 最大任务数 */
	maxTasks = 10

	/** 全选 */
	get selectAll() {
		return this.items.length > 0 && this.items.every(x => x.selected)
	}
	set selectAll(value) {
		this.items.forEach(x => x.selected = value)
	}

	/** 选中的任务数量 */
	get selectedCount() {
		return this.items.filter(x => x.selected).length
	}

	connectedCallback() {
		super.connectedCallback()
		updatables.add(() => this.updateQueue())
	}

	/** 渲染单元格 */
	render(key: string, val: any) {
		switch (typeof val) {
			case 'number':
				if (key == 'time')
					return new Date(val).toLocaleString()
				return val + ''
		}
		return val == null ? '' : val
	}

	/** 更新队列 */
	updateQueue() {
		for (let i = 0; i < this.items.length;) {
			const task = this.items[i++]
			if (!task.paused) {
				if (this.update(task)) {
					if (!world.mode || --task.remainTime <= 0) {
						this.items.splice(--i, 1)
						qTable.page.updateValue('data')
						finish(task)
					}
				} else
					task.paused = true
			}
		}
	}

	/** 更新任务 */
	update(task: Task) {
		if (task.value >= 0) {
			const progress = Math.round(7 * task.remainTime / task.time)
			put(task.slot, task.value | progress << 12)
		}
		let err = task.recipeId >= 0 ?
			tryApply(task.slot, task.recipeId, task.k || 1) : 0
		if (err & 255)
			err = tryApply(-1, task.recipeId, task.k || 1)
		if (err) {
			let msg = `${task.name}已暂停：`
			if ((err & 255) > 4)
				msg += names[err >> 8]
			error(msg + errors[err & 255])
		}
		return err == 0
	}

	/** 开始/暂停选中任务 */
	switch() {
		for (const item of this.items)
			if (item.selected)
				item.paused = !item.paused
	}

	/** 取消选中的任务 */
	cancel() {
		const tasks = world.tasks
		const items = this.items
		for (let i = items.length; --i >= 0;) {
			const item = items[i]
			if (item.selected) {
				const i = tasks.findIndex(select(item))
				if (i >= 0) {
					tasks.splice(i, 1)
					put(item.slot, item.oldValue)
					qTable.page.updateValue('data')
				}
			}
		}
	}

	async updateContents(p: CPagination, f?: DataFilter) {
		this.items = processData(world.tasks, p, f)
	}

	toCoord = toCoord
}

const [qTable] = document.getElementsByTagName('q-table')

const select = (item: TaskBase) =>
	(x: Task) => x.slot == item.slot

/** 添加任务 */
export function queue(task: TaskBase) {
	if (world.tasks.length >= qTable.maxTasks)
		error('任务队列已满')
	else {
		if (world.tasks.find(select(task))) {
			error('该位置已有任务')
			return
		}

		(<Task>task).time = task.remainTime
		const tile = getTile(task.slot);
		(<Task>task).oldValue = tile[2] | (tile[3] & 15) << 8
		world.tasks.push(<Task>task)
		qTable.page.updateValue('data')
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'q-table': QTable
	}
}
